'/
' MOTEP - Massive Online Text Environment Project
' --------------------------------------------------------------------------------
' Shared Code
' 
' Console.bmx
' 
' (c) Anton Berlin. All Rights Reserved.
'/


'// The current input from the game console.
global conInputText:string

'// The list of currently available commands.
global commandList:TList = CreateList() 



'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'//		Command template.
'// -----------------------------------------------------------------------------------------------------------------
type TCommand abstract

	'// Mandatory method that gets executed when the command is called.
	'//		(string) args: The arguments that were thrown to the command.
	method Execute:byte(args:string = null) abstract
	
	'// Mandatory method that returns the name of the command. This is what you have to enter to the game
	'// console to call the command. It's basically an identifier.
	method Name:string() abstract

end type

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'//		Extract the command from the text string (i.e. the first word in the string).
'// -----------------------------------------------------------------------------------------------------------------
function getCmd:string(textString:string); return lower(str.word(0, textString)); end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'//		Extract the arguments from the text string (i.e. everything BUT the first word of the string).
'// -----------------------------------------------------------------------------------------------------------------
function getArgs:string(textString:string)

	local returnedString:string
	
	if (not str.words(textString) - 1) ..
		return null
	
	for local i:int = 1 until str.words(textString)
	
		if (returnedString) ..
			returnedString = returnedString + " " + str.word(i, textString) ..
		else ..
			returnedString = str.word(i, textString)
	
	next
	
	return lower(returnedString)

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'//		Extract a specific argument from the text string.
'// -----------------------------------------------------------------------------------------------------------------
function argument:string(textString:string, a:int); return str.word(a, getArgs(textString)); end function



'/
' Use handleCmds and handleConsole like this:
' 
' 	global consoleCommand:string
' 	global commandList:TList = CreateList()
' 	
' 	function main()
' 		for local i:int = 0 to 1000000
' 			commandList = gatherCommands() ' Gather all commands that are available at the moment
' 			consoleCommand = consoleInput()
' 			if (not handleCmds(commandList, consoleCommand)) ..
' 				Print("Invalid command.")
' 			consoleCommand = null
'		next
' 	end function
' 
' Remember to create a function that gathers all commands that are
' available at any current moment in time.
'/

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'//		Handle the commands that the user inputs.
'// 
'// Parameters:
'//		(string) commands
'//		(TList) commandList
'// -----------------------------------------------------------------------------------------------------------------
function handleCmds:byte(commands:string, commandList:TList)

	if (not commands) ..
		return 1
	
	if (commands) then
	
		local success:byte = 0
		
		for local c:TCommand = eachin commandList
		
			if (lower(c.Name()) = getCmd(commands)) then
			
				if (c.Execute(getArgs(commands))) ..
					success = 1 ..
				else ..
					success = 0
				
				exit
			
			end if
		
		next
		
		if (not success) ..
			return 0
		
		return 1
	
	end if

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'//		Function for handling the input to a console.
'// -----------------------------------------------------------------------------------------------------------------
function consoleInput:string()

	local commands:string
	local currentKeyStroke:int = getKeyStroke() 
	
	if (currentKeyStroke <> null) then
	
		if (currentKeyStroke = KEY_ENTER) then
		
			commands = conInputText
			conInputText = null
			flushInput()
		
		else if (currentKeyStroke = KEY_ESCAPE) then
		
			conInputText = null
			flushInput()
		
		else if (currentKeyStroke = KEY_BACKSPACE) then
		
			if (conInputText <> null) then
			
				conInputText = Mid(conInputText, 0, Len(conInputText))
				flushInput()
			
			end if
		
		else if (writableKey(currentKeyStroke) = true) then
		
			conInputText = conInputText + Chr(currentKeyStroke)
			flushInput()
		
		end if
	
	end if
	
	return commands

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'//		Flush the input.
'// -----------------------------------------------------------------------------------------------------------------
function flushInput()

	FlushKeys()
	FlushMouse()

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'//		Get the allowed keystroke, if there is any, and return it.
'// -----------------------------------------------------------------------------------------------------------------
function getKeyStroke:int()

	local currentKeyStroke:int
	
	'// Get the current keystroke.
	local temp = GetChar()
	
	'// Numbers.
	if (temp = KEY_0)			currentKeyStroke = KEY_0
	if (temp = KEY_1)			currentKeyStroke = KEY_1
	if (temp = KEY_2)			currentKeyStroke = KEY_2
	if (temp = KEY_3)			currentKeyStroke = KEY_3
	if (temp = KEY_4)			currentKeyStroke = KEY_4
	if (temp = KEY_5)			currentKeyStroke = KEY_5
	if (temp = KEY_6)			currentKeyStroke = KEY_6
	if (temp = KEY_7)			currentKeyStroke = KEY_7
	if (temp = KEY_8)			currentKeyStroke = KEY_8
	if (temp = KEY_9)			currentKeyStroke = KEY_9
	
	'// Lowercase letters.
	if (temp = KEY_A)			currentKeyStroke = KEY_A
	if (temp = KEY_B)			currentKeyStroke = KEY_B
	if (temp = KEY_C)			currentKeyStroke = KEY_C
	if (temp = KEY_D)			currentKeyStroke = KEY_D
	if (temp = KEY_E)			currentKeyStroke = KEY_E
	if (temp = KEY_F)			currentKeyStroke = KEY_F
	if (temp = KEY_G)			currentKeyStroke = KEY_G
	if (temp = KEY_H)			currentKeyStroke = KEY_H
	if (temp = KEY_I)			currentKeyStroke = KEY_I
	if (temp = KEY_J)			currentKeyStroke = KEY_J
	if (temp = KEY_K)			currentKeyStroke = KEY_K
	if (temp = KEY_L)			currentKeyStroke = KEY_L
	if (temp = KEY_M)			currentKeyStroke = KEY_M
	if (temp = KEY_N)			currentKeyStroke = KEY_N
	if (temp = KEY_O)			currentKeyStroke = KEY_O
	if (temp = KEY_P)			currentKeyStroke = KEY_P
	if (temp = KEY_Q)			currentKeyStroke = KEY_Q
	if (temp = KEY_R)			currentKeyStroke = KEY_R
	if (temp = KEY_S)			currentKeyStroke = KEY_S
	if (temp = KEY_T)			currentKeyStroke = KEY_T
	if (temp = KEY_U)			currentKeyStroke = KEY_U
	if (temp = KEY_V)			currentKeyStroke = KEY_V
	if (temp = KEY_W)			currentKeyStroke = KEY_W
	if (temp = KEY_X)			currentKeyStroke = KEY_X
	if (temp = KEY_Y)			currentKeyStroke = KEY_Y
	if (temp = KEY_Z)			currentKeyStroke = KEY_Z
	if (temp = KEY_AA)			currentKeyStroke = KEY_AA
	if (temp = KEY_AE)			currentKeyStroke = KEY_AE
	if (temp = KEY_OE)			currentKeyStroke = KEY_OE
	
	'// Uppercase letters.
	if (temp = KEY_A_LC)		currentKeyStroke = KEY_A_LC
	if (temp = KEY_B_LC)		currentKeyStroke = KEY_B_LC
	if (temp = KEY_C_LC)		currentKeyStroke = KEY_C_LC
	if (temp = KEY_D_LC)		currentKeyStroke = KEY_D_LC
	if (temp = KEY_E_LC)		currentKeyStroke = KEY_E_LC
	if (temp = KEY_F_LC)		currentKeyStroke = KEY_F_LC
	if (temp = KEY_G_LC)		currentKeyStroke = KEY_G_LC
	if (temp = KEY_H_LC)		currentKeyStroke = KEY_H_LC
	if (temp = KEY_I_LC)		currentKeyStroke = KEY_I_LC
	if (temp = KEY_J_LC)		currentKeyStroke = KEY_J_LC
	if (temp = KEY_K_LC)		currentKeyStroke = KEY_K_LC
	if (temp = KEY_L_LC)		currentKeyStroke = KEY_L_LC
	if (temp = KEY_M_LC)		currentKeyStroke = KEY_M_LC
	if (temp = KEY_N_LC)		currentKeyStroke = KEY_N_LC
	if (temp = KEY_O_LC)		currentKeyStroke = KEY_O_LC
	if (temp = KEY_P_LC)		currentKeyStroke = KEY_P_LC
	if (temp = KEY_Q_LC)		currentKeyStroke = KEY_Q_LC
	if (temp = KEY_R_LC)		currentKeyStroke = KEY_R_LC
	if (temp = KEY_S_LC)		currentKeyStroke = KEY_S_LC
	if (temp = KEY_T_LC)		currentKeyStroke = KEY_T_LC
	if (temp = KEY_U_LC)		currentKeyStroke = KEY_U_LC
	if (temp = KEY_V_LC)		currentKeyStroke = KEY_V_LC
	if (temp = KEY_W_LC)		currentKeyStroke = KEY_W_LC
	if (temp = KEY_X_LC)		currentKeyStroke = KEY_X_LC
	if (temp = KEY_Y_LC)		currentKeyStroke = KEY_Y_LC
	if (temp = KEY_Z_LC)		currentKeyStroke = KEY_Z_LC
	if (temp = KEY_AA_LC)		currentKeyStroke = KEY_AA_LC
	if (temp = KEY_AE_LC)		currentKeyStroke = KEY_AE_LC
	if (temp = KEY_OE_LC)		currentKeyStroke = KEY_OE_LC
	
	'// Special keys.
	if (temp = KEY_COMMA)		currentKeyStroke = KEY_COMMA
	if (temp = KEY_PERIOD)		currentKeyStroke = KEY_PERIOD
	if (temp = KEY_EXCLAMATION)	currentKeyStroke = KEY_EXCLAMATION
	if (temp = KEY_QUOTES)		currentKeyStroke = KEY_QUOTES
	if (temp = KEY_COLON)		currentKeyStroke = KEY_COLON
	if (temp = KEY_SEMICOLON)	currentKeyStroke = KEY_SEMICOLON
	if (temp = KEY_SLASH)		currentKeyStroke = KEY_SLASH
	if (temp = KEY_NUMBER)		currentKeyStroke = KEY_NUMBER
	if (temp = KEY_HYPHEN)		currentKeyStroke = KEY_HYPHEN
	if (temp = KEY_DOLLAR)		currentKeyStroke = KEY_DOLLAR
	if (temp = KEY_AMPER)		currentKeyStroke = KEY_AMPER
	if (temp = KEY_APOSTR)		currentKeyStroke = KEY_APOSTR
	if (temp = KEY_PLUS)		currentKeyStroke = KEY_PLUS
	if (temp = KEY_PERCENT)		currentKeyStroke = KEY_PERCENT
	if (temp = KEY_ATSIGN)		currentKeyStroke = KEY_ATSIGN
	if (temp = KEY_UNDERSCR)		currentKeyStroke = KEY_UNDERSCR
	if (temp = KEY_ASTERISK)		currentKeyStroke = KEY_ASTERISK
	if (temp = KEY_QUESTION)		currentKeyStroke = KEY_QUESTION
	if (temp = KEY_LESSER)		currentKeyStroke = KEY_LESSER
	if (temp = KEY_EQUAL)		currentKeyStroke = KEY_EQUAL
	if (temp = KEY_GREATER)		currentKeyStroke = KEY_GREATER
	if (temp = KEY_LEFTPAR)		currentKeyStroke = KEY_LEFTPAR
	if (temp = KEY_RIGHTPAR)		currentKeyStroke = KEY_RIGHTPAR
	if (temp = KEY_VERTBAR)		currentKeyStroke = KEY_VERTBAR
	if (temp = KEY_BACKSPACE)	currentKeyStroke = KEY_BACKSPACE
	
	'// Keys you don't want to spam by holding them down.
	if (KeyHit(KEY_UP))			currentKeyStroke = KEY_UP
	if (KeyHit(KEY_DOWN))		currentKeyStroke = KEY_DOWN
	if (KeyHit(KEY_LEFT))		currentKeyStroke = KEY_LEFT
	if (KeyHit(KEY_RIGHT))		currentKeyStroke = KEY_RIGHT
	if (KeyHit(KEY_SPACE))		currentKeyStroke = KEY_SPACE
	if (KeyHit(KEY_ENTER))		currentKeyStroke = KEY_ENTER
	if (KeyHit(KEY_ESCAPE))		currentKeyStroke = KEY_ESCAPE
	if (KeyHit(KEY_TAB))		currentKeyStroke = KEY_TAB
	
	return currentKeyStroke

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'//		Check if a key is writable.
'// 
'// Parameters:
'// 		(int) key: The keycode to the key that you want to check.
'// -----------------------------------------------------------------------------------------------------------------
function writableKey(key:int)

	select (key)
	
		case KEY_0			return true
		case KEY_1			return true
		case KEY_2			return true
		case KEY_3			return true
		case KEY_4			return true
		case KEY_5			return true
		case KEY_6			return true
		case KEY_7			return true
		case KEY_8			return true
		case KEY_9			return true
		case KEY_A			return true
		case KEY_B			return true
		case KEY_C			return true
		case KEY_D			return true
		case KEY_E			return true
		case KEY_F			return true
		case KEY_G			return true
		case KEY_H			return true
		case KEY_I			return true
		case KEY_J			return true
		case KEY_K			return true
		case KEY_L			return true
		case KEY_M			return true
		case KEY_N			return true
		case KEY_O			return true
		case KEY_P			return true
		case KEY_Q			return true
		case KEY_R			return true
		case KEY_S			return true
		case KEY_T			return true
		case KEY_U			return true
		case KEY_V			return true
		case KEY_W			return true
		case KEY_X			return true
		case KEY_Y			return true
		case KEY_Z			return true
		case KEY_AA			return true
		case KEY_AE			return true
		case KEY_OE			return true
		case KEY_A_LC			return true
		case KEY_B_LC			return true
		case KEY_C_LC			return true
		case KEY_D_LC			return true
		case KEY_E_LC			return true
		case KEY_F_LC			return true
		case KEY_G_LC 			return true
		case KEY_H_LC			return true
		case KEY_I_LC			return true
		case KEY_J_LC			return true
		case KEY_K_LC			return true
		case KEY_L_LC			return true
		case KEY_M_LC			return true
		case KEY_N_LC			return true
		case KEY_O_LC			return true
		case KEY_P_LC			return true
		case KEY_Q_LC			return true
		case KEY_R_LC			return true
		case KEY_S_LC			return true
		case KEY_T_LC			return true
		case KEY_U_LC			return true
		case KEY_V_LC			return true
		case KEY_W_LC			return true
		case KEY_X_LC			return true
		case KEY_Y_LC			return true
		case KEY_Z_LC			return true
		case KEY_AA_LC			return true
		case KEY_AE_LC			return true
		case KEY_OE_LC			return true
		case KEY_SPACE			return true
		case KEY_COMMA 		return true
		case KEY_PERIOD 		return true
		case KEY_EXCLAMATION	return true
		case KEY_QUOTES 		return true
		case KEY_COLON 		return true
		case KEY_SEMICOLON 		return true
		case KEY_SLASH 		return true
		case KEY_NUMBER 		return true
		case KEY_HYPHEN 		return true
		case KEY_DOLLAR 		return true
		case KEY_AMPER 		return true
		case KEY_APOSTR 		return true
		case KEY_PLUS 			return true
		case KEY_PERCENT		return true
		case KEY_ATSIGN 		return true
		case KEY_UNDERSCR 		return true
		case KEY_ASTERISK 		return true
		case KEY_QUESTION 		return true
		case KEY_LESSER		return true
		case KEY_EQUAL 		return true
		case KEY_GREATER 		return true
		case KEY_LEFTPAR 		return true
		case KEY_RIGHTPAR 		return true
		case KEY_VERTBAR 		return true
		default				return false
	
	end select

end function
